//
//  News.h
//  symbrion
//
//  Created by Berend Weel on 4/15/13.
//  Copyright (c) 2013 Berend Weel. All rights reserved.
//

#ifndef symbrion_News_h
#define symbrion_News_h

#include <ostream>
#include <vector>
#include <boost/lexical_cast.hpp>
#include "Fixed32.h"
#include "Individual.h"

class News {
public:
    News(LIOReal timestamp, Individual *individual){
        this->timestamp = floor(timestamp*10 + 0.5) / 10; // rounded to 1 decimal
        this->individual = individual;
    }
    
    News(const News &other){
        this->timestamp = other.timestamp;
        this->individual = other.individual;
    }

    // Example string:
    //[news@92.4:1:0.990261:-3.99982,-3.31974,0.810821,3.13289,3.74365,-2.48248,0.119807,-0.815933,-1.89675,1.9481,-3.28362,0.483119,0.657838,2.47653,0.73535,0.0937004,3.01307,3.96068,1.80969,3.73289,-1.62318,-0.591593,3.19598,1.22399,3.21227,3.69226,-2.6823,2.8639,3.25476,-1.64779,3.48995,-0.682843,-1.53235,0.119143,-0.836562,2.31828,1.51313,0.354182,0.739259,-3.25096,0.875877,-0.541924,0.796395,2.75942,-0.0609438,2.18277,-3.4267,-2.46513,-2.21114,2.24293,-3.32826,-2.54925,0.933576,0.633132,1.91449,-1.48695,-0.489252,-0.704123,3.27111,3.93844,0.616464,-2.68862,1.58817,-1.32121,-0.35374,-3.39025,-2.96962,-2.60381,-0.465781,-3.7016,0.0333065,-0.260682,0.632127,1.3929,-3.25271,-3.46637,2.66162,-0.88174,-2.47309,-2.67681,3.66837,3.92643,-3.09148,2.96511,0.978007,1.38122,0.912364,0.701647,-2.79277,-1.95988,2.39151,0.744364,3.17321,-1.82624,-2.4164,-1.83615,-0.829053,-3.23256,1.18467,1.06045,-2.99929,-2.78982,-3.28919,3.5909,0.325088,-3.65917,0.399782,1.88071,-0.123641,-0.276024,-3.94196,-2.21968,-2.35055,0.571874,-3.07993,0.836555,-2.6389,1.58401,-2.04774,1.31749,-3.66917,-2.61078,-1.07323,2.01196,-0.852963,2.59934,0.507842,2.02477,1.54077,-1.44761,2.6275,0.26041,2.24328,-2.81957,0.682694,2.34103,3.61947,3.30025,2.26907,2.35505,0.576497,-3.92473,-2.77666,0.0804228,2.09033,-1.63525,0.811595,0.479352,2.77699,0.0333801,3.29155,-1.51987,2.34783,3.86063,-3.49088,3.71564,-2.2223,-0.411491,0.910328,-1.57189,3.33957,-3.55033,-2.11186,2.41535,-0.509211,3.8705,0.910452,-3.5915,2.73286,-2.08157,0.418074,-3.1624,3.59272,0.278375,-2.56982,0.171256,2.68166,-1.36016,-0.479158,-1.4589,1.65822,3.82287,-2.37489,1.88069,-1.10386,3.62893,-3.72637,-3.60425,3.0372,0.580304,3.85433,-3.51324,-3.45096,2.49303,-3.04688,3.83349,-1.54167,-2.1934,2.53235,-0.749044]
    News(std::string description){
        std::string parsing = description;
        
        size_t start = parsing.find("@")+1;
        size_t num = parsing.find(":") - start;
        std::string time = parsing.substr(start,num);
        timestamp = boost::lexical_cast<LIOReal>(time);
        
        parsing.erase(0,parsing.find(":")+1);
        
        individual = new Individual();
        
        std::string idstr = parsing.substr(0,parsing.find(":"));
        individual->id = boost::lexical_cast<int>(idstr);
        
        parsing.erase(0,parsing.find(":")+1);
        std::string sigma = parsing.substr(0,parsing.find(":"));
        individual->sigma = boost::lexical_cast<LIOReal>(sigma);
        
        parsing.erase(0,parsing.find(":")+1);
        std::string fitness = parsing.substr(0,parsing.find(":"));
        individual->fitness = boost::lexical_cast<LIOReal>(fitness);
        individual->hasFitness = true;
        
        start = parsing.find(":")+1;
        num = parsing.find("]") - start;
        std::string values = parsing.substr(start,num);
        size_t pos;
        while((pos = values.find(",")) != std::string::npos){
            std::string value = values.substr(0,pos);
            values.erase(0,pos+1);
            
            individual->genome.push_back(boost::lexical_cast<LIOReal>(value));
        }
        // Add the last value
        individual->genome.push_back(boost::lexical_cast<LIOReal>(values));
    }
    
    virtual ~News (){
        delete individual;
    }
    
    LIOReal getTimestamp() const {return timestamp;}
    Individual *getIndividual() const {return individual;}
    
private:
    LIOReal timestamp;
    Individual *individual;
};

inline News* new_clone( const News& news ) {
    return new News(news);
}

bool newsLessThanp(News *one, News *other);
bool newsGreaterThanp(News *one, News *other);
bool newsEqualp(News *one, News *other);
bool newsNotEqualp(News *one, News *other);

bool newsLessThan(const News &one, const News &other);
bool newsGreaterThan(const News &one, const News &other);
bool newsEqual(const News &one, const News &other);
bool newsNotEqual(const News &one, const News &other);

std::ostream& operator<<(std::ostream& out, const News& news);
bool operator==( const News& one, const News& other);
bool operator<(const News& one, const News& other);
bool operator>(const News& one, const News& other);
#endif
